<?php

namespace App\Services\Ocean\Report;

use App\Common\Helpers\Functions;
use App\Common\Tools\CustomException;
use App\Services\Ocean\OceanService;
use Illuminate\Support\Facades\DB;

class OceanReportV2Service extends OceanService
{
    /**
     * @var string
     * 模型类
     */
    public $modelClass;

    /**
     * @var
     * 过滤条件
     */
    protected $filtering = [];

    /**
     * constructor.
     * @param string $appId
     */
    public function __construct($appId = ''){
        parent::__construct($appId);
    }

    /**
     * @param array $option
     * @return bool
     * @throws CustomException
     * 同步
     */
    public function sync($option = []){
        ini_set('memory_limit', '2048M');

        $t = microtime(1);

        $accountIds = [];
        // 账户id过滤
        if(!empty($option['account_ids'])){
            $accountIds = $option['account_ids'];
        }

        // 并发分片大小
        if(!empty($option['multi_chunk_size'])){
            $multiChunkSize = min(intval($option['multi_chunk_size']), 8);
            $this->sdk->setMultiChunkSize($multiChunkSize);
Functions::consoleDump("multi chunk size: {$multiChunkSize}");
        }

        $dateRange = Functions::getDateRange($option['date']);
        $dateList = Functions::getDateListByRange($dateRange);

        // 删除
        if(!empty($option['delete'])){
            $between = [
                $dateRange[0] .' 00:00:00',
                $dateRange[1] .' 23:59:59',
            ];

            $model = new $this->modelClass();

            $builder = $model->whereBetween('stat_datetime', $between);

            if(!empty($accountIds)){
                $builder->whereIn('account_id', $accountIds);
            }

            $builder->delete();
        }

        if(!empty($option['run_by_new_account'])){
            // 新账户
            $accountIds = $this->getNewAccount($accountIds, 14);
            var_dump($accountIds);
        }

        if(!empty($option['has_history_cost'])){
            // 历史消耗
            $accountIds = $this->getHasHistoryCostAccount($accountIds);
        }

        // 获取子账户组
        $accountGroup = $this->getSubAccountGroup($accountIds);

        $this->setFiltering($option);

        $filtering = $this->getFiltering();

        foreach($dateList as $date){
            $fields = ["stat_cost", "show_cnt", "click_cnt", "convert_cnt"];
            $dimensionsMap = [
                'cdp_project_id' => 'project_id',
                'cdp_promotion_id' => 'promotion_id',
                'stat_time_hour' => 'stat_datetime',
                'stat_time_day' => 'stat_datetime',
                'material_id' => 'material_id',
            ];
            $metricsMap = [
                'stat_cost' => 'cost',
                'show_cnt' => 'show',
                'click_cnt' => 'click',
                'convert_cnt' => 'convert',
            ];
            $param = [
                'start_time' => $date,
                'end_time' => $date,
                'dimensions' => $this->getReprotDimensions(),
                'metrics' => $fields,
                'filters' => $this->filtering,
                'order_by' => [
                    ['field' => 'stat_cost', 'type' => 'DESC']
                ],
            ];

            if(!empty($this->getGroupBy())){
                $param['group_by'] = $this->getGroupBy();
            }

            $pageSize = 100;
            foreach($accountGroup as $g){
                $items = $this->multiGetPageList($g, $filtering, $pageSize, $param);

                Functions::consoleDump('count:'. count($items));

                $cost = 0;

                // 保存
                $data = [];
                foreach($items as $item) {
                    Functions::isLocal() && var_dump($item);

                    foreach($item['dimensions'] as $k => $v){
                        if(isset($dimensionsMap[$k])){
                            $item[$dimensionsMap[$k]] = $v;
                        }
                    }

                    foreach($item['metrics'] as $k => $v){
                        if(isset($metricsMap[$k])){
                            $item[$metricsMap[$k]] = $v;
                        }

                        if(!in_array($k, $fields)){
                            continue;
                        }

                        if(!isset($item[$k])){
                            $item[$k] = 0;
                        }

                        $item[$k] += $v;
                    }

                    $cost += $item['stat_cost'];

                    if(!$this->itemValid($item)){
                        continue;
                    }

                    $item['stat_datetime'] = substr($item['stat_datetime'], 0, 16) . ':00';
                    $item['cost'] *= 100;
                    $item['stat_cost'] *= 100;
                    $item['extends'] = json_encode($item);

                    $data[] = $item;
                }

                // 批量保存
                $this->batchSave($data);

                Functions::consoleDump('cost:'. $cost);
            }
        }

        $t = microtime(1) - $t;
        Functions::consoleDump($t);

        return true;
    }

    /**
     * @param $item
     * @return bool
     * 校验
     */
    protected function itemValid($item){
        $valid = true;

        if(
            empty($item['stat_cost']) &&
            empty($item['show_cnt']) &&
            empty($item['click_cnt']) &&
            empty($item['convert_cnt'])
        ){
            $valid = false;
        }

        return $valid;
    }

    /**
     * @return array
     * 获取分组
     */
    protected function getGroupBy(){
        return [];
    }

    /**
     * @param $option
     * @return bool
     * 设置过滤条件
     */
    protected function setFiltering($option){
        return true;
    }

    /**
     * @return array
     * 获取过滤条件
     */
    protected function getFiltering(){
        return $this->filtering;
    }

    /**
     * @param $data
     * @return bool
     * 批量保存
     */
    public function batchSave($data){
        $model = new $this->modelClass();
        $model->chunkInsertOrUpdate($data);
        return true;
    }

    /**
     * @param string $date
     * @return mixed
     * @throws CustomException
     * 按日期获取账户报表
     */
    public function getAccountReportByDate($date = 'today'){
        $date = Functions::getDate($date);
        Functions::dateCheck($date);

        $model = new $this->modelClass();
        $report = $model->whereBetween('stat_datetime', ["{$date} 00:00:00", "{$date} 23:59:59"])
            ->groupBy('account_id')
            ->orderBy('cost', 'DESC')
            ->select(DB::raw("account_id, SUM(cost) cost"))
            ->get();

        return $report;
    }

    /**
     * @return string
     * 获取时间维度
     */
    public function getTimeGranularity(){
        return 'STAT_TIME_GRANULARITY_HOURLY';
    }

    /**
     * @return array
     * 获取报表维度
     */
    public function getReprotDimensions(){
        return [];
    }
}
